package com.jwetherell.my;

import java.util.Arrays;

import com.jwetherell.algorithms.data_structures.basic.List;

public class ArrayList<T> extends List<T> {

	private static final int DEFAULT_SIZE = 10;

	private Object [] data;
	private int size = 0; // no. of elements contained at this point of time
	
	public ArrayList() {
		data = new Object[DEFAULT_SIZE];
	}
	
	public ArrayList(int size) {
		if (size < 0)
			throw new IllegalArgumentException("Invalid size: " + size);
		data = new Object[size];
	}
	
	@Override
	public void add(T value) {
		
		if (data.length < size)
			data = Arrays.copyOf(data, 2 * data.length);
		
		data[size] = value;
		size++;
	}

	@Override
	public boolean remove(T value) {
		
		int index = indexOf(value);
		
		if (index == -1)
			return false;
		else {
			
			if (index == (size - 1)) {
				data[size] = null;
				size--;
				return true;
			}
			
			for (int j = index; index < (size - 1); j++) {
				data[j] = data[j+1];
			}
			size--;
			
			return true;
		}
	}

	/**
     * Returns the index of the first occurrence of the specified element
     * in this list, or -1 if this list does not contain the element.
     * More formally, returns the lowest index <tt>i</tt> such that
     * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,
     * or -1 if there is no such index.
     */
	public int indexOf(T value) {
		
		if (value == null) {
			for (int i = 0; i < size; i++) {
				if (data[i] ==  null)
					return i;
			}
		} else {
			for (int i = 0; i < size; i++) {
				if (data[i].equals(value))
					return i;
			}
		}
		
		return -1;
	}
	
    /**
     * Returns <tt>true</tt> if this list contains the specified element.
     * More formally, returns <tt>true</tt> if and only if this list contains
     * at least one element <tt>e</tt> such that
     * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
     *
     * @param o element whose presence in this list is to be tested
     * @return <tt>true</tt> if this list contains the specified element
     */
	@Override
	public boolean contains(T value) {
		return indexOf(value) >= 0;
	}

	@SuppressWarnings("unchecked")
	@Override
	public T get(int index) {
		
		if (index < 0)
			throw new IllegalArgumentException("Index can't be less than 0");
		
		if (index >= size)
			throw new IndexOutOfBoundsException();
		
		return (T) data[index];
	}

	@Override
	public int size() {
		return size;
	}

}